/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package service;

import co.edu.unal.satacredito.database.connection.TransactionDatastoreFactory;
import co.edu.unal.satacredito.database.dao.ReportMongoDao;
import co.edu.unal.satacredito.database.entity.Transaction;
import com.google.code.morphia.Datastore;
import VO.Constants;
import VO.TransactionVO;
import co.edu.unal.satacredito.database.constants.FileLogConstants;
import co.edu.unal.satacredito.database.constants.TransactionConstants;
import co.edu.unal.satacredito.database.dao.FileLogMongoDao;
import co.edu.unal.satacredito.database.dao.TransactionMongoDao;
import co.edu.unal.satacredito.database.entity.FileLog;
import co.edu.unal.satacredito.database.exception.UnreachableHostException;
import java.net.UnknownHostException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.bson.types.ObjectId;

/**
 *
 * @author julianDavidPG
 */
public class TransactionService {
    
    private Datastore datastore;
    
    private ReportMongoDao rdao;
    
    private FileLogMongoDao fdao;
    
    private TransactionMongoDao tdao;
    
    private static final SimpleDateFormat FORMAT = new SimpleDateFormat("dd/MM/yyyy");
    
    public List<TransactionVO> getTransactions(String initialDate, String finalDate, String establishmentID, 
                                        String brandID, String franchiseID, String reportType, long initAmount, long finAmount){
        List<Transaction> list = null;
        List<TransactionVO> finalList = null;
        
        boolean searchByAmount = false;
        if (initAmount != 0d) {
            searchByAmount = true;
        }
        if (finAmount != 0d) {
            searchByAmount = true;
        }
        try {
            Date initDate;
            Date finDate;
            if (initialDate.equals(Constants.noDateFilter)) {
                initDate = FORMAT.parse("01/01/1000");
            } else {
                initDate = stringToDate(initialDate);
            }
            if (finalDate.equals(Constants.noDateFilter)) {
                finDate = FORMAT.parse("31/12/9999");
            } else {
                finDate = stringToDate(finalDate);
            }
            datastore = TransactionDatastoreFactory.createDatastore();
            ObjectId franchiseId = null;
            ObjectId brandId = null;
            ObjectId establishmentId = null;
            if (!franchiseID.equals(Constants.AllFranchise)) {
                franchiseId = new ObjectId(franchiseID);
            }
            if (!brandID.equals(Constants.AllBrand)) {
                brandId = new ObjectId(brandID);
            }
            if (!establishmentID.equals(Constants.AllEstablishment)) {
                establishmentId = new ObjectId(establishmentID);
            }
            rdao = new ReportMongoDao(datastore);
            if (reportType.equals(Constants.typeValidTransaction)) {
                if (!searchByAmount && franchiseID.equals(Constants.AllFranchise) && establishmentID.equals(Constants.AllEstablishment)) {
                    list = rdao.findApprovedByDateRangeAndBrand(initDate, finDate, brandId);
                } else if (!searchByAmount && franchiseID.equals(Constants.AllFranchise) && !establishmentID.equals(Constants.AllEstablishment)) {
                    list = rdao.findApprovedByDateRangeAndEstablishment(initDate, finDate, establishmentId);
                } else if (!searchByAmount && !franchiseID.equals(Constants.AllFranchise) && !establishmentID.equals(Constants.AllEstablishment)) {
                    list = rdao.findApprovedByDateRangeAndEstablishmentAndFranchise(initDate, finDate, establishmentId, franchiseId);
                } else if (!searchByAmount && !franchiseID.equals(Constants.AllFranchise) && establishmentID.equals(Constants.AllEstablishment)) {
                    list = rdao.findApprovedByDateRangeAndBrandAndFranchise(initDate, finDate, brandId, franchiseId);
                } else if (searchByAmount && franchiseID.equals(Constants.AllFranchise) && establishmentID.equals(Constants.AllEstablishment)) {
                    list = rdao.findApprovedByDateRangeAndBrandAndAmountRange(initDate, finDate, brandId, initAmount, finAmount);
                } else if (searchByAmount && franchiseID.equals(Constants.AllFranchise) && !establishmentID.equals(Constants.AllEstablishment)) {
                    list = rdao.findApprovedByDateRangeAndEstablishmentAndAmountRange(initDate, finDate, establishmentId, initAmount, finAmount);
                } else if (searchByAmount && !franchiseID.equals(Constants.AllFranchise) && !establishmentID.equals(Constants.AllEstablishment)) {
                    list = rdao.findApprovedByDateRangeAndEstablishmentAndFranchiseAndAmountRange(initDate, finDate, establishmentId, franchiseId, initAmount, finAmount);
                } else if (searchByAmount && !franchiseID.equals(Constants.AllFranchise) && establishmentID.equals(Constants.AllEstablishment)) {
                    list = rdao.findApprovedByDateRangeAndBrandAndFranchiseAndAmountRange(initDate, finDate, brandId, franchiseId, initAmount, finAmount);
                }
            } else if (reportType.equals(Constants.typeInvalidTransaction)) {
                if (!searchByAmount && franchiseID.equals(Constants.AllFranchise) && establishmentID.equals(Constants.AllEstablishment)) {
                    list = rdao.findFailedByDateRangeAndBrand(initDate, finDate, brandId);
                } else if (!searchByAmount && franchiseID.equals(Constants.AllFranchise) && !establishmentID.equals(Constants.AllEstablishment)) {
                    list = rdao.findFailedByDateRangeAndEstablishment(initDate, finDate, establishmentId);
                } else if (!searchByAmount && !franchiseID.equals(Constants.AllFranchise) && !establishmentID.equals(Constants.AllEstablishment)) {
                    list = rdao.findFailedByDateRangeAndEstablishmentAndFranchise(initDate, finDate, establishmentId, franchiseId);
                } else if (!searchByAmount && !franchiseID.equals(Constants.AllFranchise) && establishmentID.equals(Constants.AllEstablishment)) {
                    list = rdao.findFailedByDateRangeAndBrandAndFranchise(initDate, finDate, brandId, franchiseId);
                } else if (searchByAmount && franchiseID.equals(Constants.AllFranchise) && establishmentID.equals(Constants.AllEstablishment)) {
                    list = rdao.findFailedByDateRangeAndBrandAndAmountRange(initDate, finDate, brandId, initAmount, finAmount);
                } else if (searchByAmount && franchiseID.equals(Constants.AllFranchise) && !establishmentID.equals(Constants.AllEstablishment)) {
                    list = rdao.findFailedByDateRangeAndEstablishmentAndAmountRange(initDate, finDate, establishmentId, initAmount, finAmount);
                } else if (searchByAmount && !franchiseID.equals(Constants.AllFranchise) && !establishmentID.equals(Constants.AllEstablishment)) {
                    list = rdao.findFailedByDateRangeAndEstablishmentAndFranchiseAndAmountRange(initDate, finDate, establishmentId, franchiseId, initAmount, finAmount);
                } else if (searchByAmount && !franchiseID.equals(Constants.AllFranchise) && establishmentID.equals(Constants.AllEstablishment)) {
                    list = rdao.findFailedByDateRangeAndBrandAndFranchiseAndAmountRange(initDate, finDate, brandId, franchiseId, initAmount, finAmount);
                }
            } else {
                if (!searchByAmount && franchiseID.equals(Constants.AllFranchise) && establishmentID.equals(Constants.AllEstablishment)) {
                    list = rdao.findFailedByDateRangeAndBrand(initDate, finDate, brandId);
                    list.addAll(rdao.findApprovedByDateRangeAndBrand(initDate, finDate, brandId));
                } else if (!searchByAmount && franchiseID.equals(Constants.AllFranchise) && !establishmentID.equals(Constants.AllEstablishment)) {
                    list = rdao.findFailedByDateRangeAndEstablishment(initDate, finDate, establishmentId);
                    list.addAll(rdao.findApprovedByDateRangeAndEstablishment(initDate, finDate, establishmentId));
                } else if (!searchByAmount && !franchiseID.equals(Constants.AllFranchise) && !establishmentID.equals(Constants.AllEstablishment)) {
                    list = rdao.findFailedByDateRangeAndEstablishmentAndFranchise(initDate, finDate, establishmentId, franchiseId);
                    list.addAll(rdao.findApprovedByDateRangeAndEstablishmentAndFranchise(initDate, finDate, establishmentId, franchiseId));
                } else if (!searchByAmount && !franchiseID.equals(Constants.AllFranchise) && establishmentID.equals(Constants.AllEstablishment)) {
                    list = rdao.findFailedByDateRangeAndBrandAndFranchise(initDate, finDate, brandId, franchiseId);
                    list.addAll(rdao.findApprovedByDateRangeAndBrandAndFranchise(initDate, finDate, brandId, franchiseId));
                } else if (searchByAmount && franchiseID.equals(Constants.AllFranchise) && establishmentID.equals(Constants.AllEstablishment)) {
                    list = rdao.findFailedByDateRangeAndBrandAndAmountRange(initDate, finDate, brandId, initAmount, finAmount);
                    list.addAll(rdao.findApprovedByDateRangeAndBrandAndAmountRange(initDate, finDate, brandId, initAmount, finAmount));
                } else if (searchByAmount && franchiseID.equals(Constants.AllFranchise) && !establishmentID.equals(Constants.AllEstablishment)) {
                    list = rdao.findFailedByDateRangeAndEstablishmentAndAmountRange(initDate, finDate, establishmentId, initAmount, finAmount);
                    list.addAll(rdao.findApprovedByDateRangeAndEstablishmentAndAmountRange(initDate, finDate, establishmentId, initAmount, finAmount));
                } else if (searchByAmount && !franchiseID.equals(Constants.AllFranchise) && !establishmentID.equals(Constants.AllEstablishment)) {
                    list = rdao.findFailedByDateRangeAndEstablishmentAndFranchiseAndAmountRange(initDate, finDate, establishmentId, franchiseId, initAmount, finAmount);
                    list.addAll(rdao.findApprovedByDateRangeAndEstablishmentAndFranchiseAndAmountRange(initDate, finDate, establishmentId, franchiseId, initAmount, finAmount));
                } else if (searchByAmount && !franchiseID.equals(Constants.AllFranchise) && establishmentID.equals(Constants.AllEstablishment)) {
                    list = rdao.findFailedByDateRangeAndBrandAndFranchiseAndAmountRange(initDate, finDate, brandId, franchiseId, initAmount, finAmount);
                    list.addAll(rdao.findApprovedByDateRangeAndBrandAndFranchiseAndAmountRange(initDate, finDate, brandId, franchiseId, initAmount, finAmount));
                }
            }
            System.out.println("result size: " + list.size());
            finalList = entityToVO(list);
        } 
        catch (UnknownHostException e) {
            System.out.println("no encontro la base de datos");
            finalList = new ArrayList<TransactionVO>();
        }catch (ParseException e) {
            System.out.println("formato de fecha incorrecto");
            finalList = new ArrayList<TransactionVO>();
        }catch (Exception e) {
            e.printStackTrace();
            finalList = new ArrayList<TransactionVO>();
        }finally{
            return finalList;
        }
    }

    private List<TransactionVO> entityToVO(List<Transaction> list) throws UnreachableHostException {
        List<TransactionVO> finalList = new ArrayList<TransactionVO>();
        for(Transaction x : list){
            TransactionVO t = new TransactionVO();
            t.setFile(x.getFileId().toString());
            fdao = new FileLogMongoDao(datastore);
            FileLog fileLog = fdao.findByFileId(x.getFileId());
            t.setEstablishmentId(fileLog.getEstablishment().toString());
            t.setBrand(fileLog.getBrand().toString());
            t.setAmount(x.getPurchaseAmount());
            t.setCheckSum(x.getTransactionId().toString());
            t.setDNIType(x.getNinType());
            t.setDNI(x.getNin());
            Date date = fileLog.getDate();
            t.setDate(String.valueOf(date.getYear() + 1900) + "-" + String.valueOf(date.getMonth() + 1) + "-" + String.valueOf(date.getDate()));
            t.setPurchaseDetail(x.getPurchaseDetail());
            t.setValidationResult(x.getValidationResult());
            t.setValidationIsue(x.getValidationIssue());
            t.setBankId(x.getBank().toString());
            finalList.add(t);
        }
        return finalList;
    }

    private Date stringToDate(String date) throws ParseException {
        String year = date.substring(0, 4);
        String month = date.substring(5, 7);
        String day = date.substring(8, 10);
        return FORMAT.parse(day + "/" + month + "/" + year);
    }

    public void fillMongo() {
        try {
            datastore = TransactionDatastoreFactory.createDatastore();
            tdao = new TransactionMongoDao(datastore);
            fdao = new FileLogMongoDao(datastore);
            FileLog fileLog = new FileLog();
            fileLog.setBrand(new ObjectId());
            System.out.println("brand: " + fileLog.getBrand().toString());
            fileLog.setDate(FORMAT.parse("05/05/2012"));
            fileLog.setEstablishment(new ObjectId());
            System.out.println("establishment1:" + fileLog.getEstablishment().toString());
            //fileLog.setFileLogId(new ObjectId());
            fileLog.setState(FileLogConstants.STATE_END);
            fileLog.setFileId(new ObjectId());
            fdao.create(fileLog);
            FileLog fileLog2 = new FileLog();
            fileLog2.setBrand(fileLog.getBrand());
            System.out.println("brand: " + fileLog.getBrand().toString());
            fileLog2.setDate(new Date());
            fileLog2.setEstablishment(new ObjectId());
            System.out.println("establishment2:" + fileLog2.getEstablishment().toString());
            //fileLog2.setFileLogId(new ObjectId());
            fileLog2.setState(FileLogConstants.STATE_END);
            fileLog2.setFileId(new ObjectId());
            fdao.create(fileLog2);
            ObjectId bank1 = new ObjectId();
            ObjectId bank2 = new ObjectId();
            ObjectId franchise1 = new ObjectId();
            System.out.println("franchise 1: " + franchise1.toString());
            ObjectId franchise2 = new ObjectId();
            System.out.println("franchise 2: " + franchise2.toString());
            for (int i = 1; i < 1000; i++) {
                Transaction t = new Transaction();
                t.setName("Name31");
                t.setMiddlename("Name32");
                t.setLastname("Lastname31 Lastname32");
                t.setNin("3000111222" + (2*i));
                t.setNinType(TransactionConstants.NIN_DOCUMENT);
                t.setCardNumber("1000000" + i);
                t.setCardCode(345);
                t.setCardType(TransactionConstants.CARD_CREDIT);
                if (i % 3 == 0) {
                    t.setValidationResult(TransactionConstants.RESULT_FAILED);
                    t.setValidationIssue(TransactionConstants.ISSUE_NIN);
                } else {
                    t.setValidationResult(TransactionConstants.RESULT_APPROVED);
                    t.setValidationIssue(TransactionConstants.ISSUE_NOT);
                }
                t.setPurchaseAmount(1028767110L + i);
                //t.setTransactionId(new ObjectId());
                if (i % 2 == 0) {
                    t.setFileId(fileLog.getFileId());
                } else {
                    t.setFileId(fileLog2.getFileId());
                }
                t.setPurchaseDetail("algo asfasdsadsa algo");
                if (i % 3 == 0) {
                    t.setBank(bank1);
                    t.setFranchise(franchise1);
                } else {
                    t.setBank(bank2);
                    t.setFranchise(franchise2);
                }
                t.setFileNumber(3);
                t.setPurchaseDate(FORMAT.parse("05/05/2012"));
                t.setValidationDate(FORMAT.parse("05/05/2012"));
                t.setReadState(TransactionConstants.READ_CLIENT);
                tdao.create(t);
        }
        } catch (ParseException ex) {
            Logger.getLogger(TransactionService.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnreachableHostException ex) {
            Logger.getLogger(TransactionService.class.getName()).log(Level.SEVERE, "erro en insercion", ex);
        } catch (UnknownHostException ex) {
            Logger.getLogger(TransactionService.class.getName()).log(Level.SEVERE, "erro en insercion", ex);
        }
        
        
    }

}
